﻿using System;
using System.Collections;
using System.IO;
using GeneralDFS.Common;
using ProtoBuf;

namespace GeneralDFS.DataEntity.IO
{
    [ProtoContract]
    [Serializable]
    public class NodeBase:IComparable<NodeBase>,IComparable
    {
        [ProtoMember(1)]
        public String Name
        {
            set;
            get;
        }

        [ProtoMember(2)]
        public long CreateTime
        {
            set;
            get;
        }

        [ProtoMember(3)]
        public long LastUpdateTime
        {
            set;
            get;
        }

        [ProtoMember(4)]
        public String CreaterName
        {
            set;
            get;
        }

        public DirectoryNodeInfo Parent
        {
            set;
            get;
        }

        [ProtoMember(5)]
        public String FullPath
        {
            set;
            get;
        }

        [ProtoMember(6)]
        public int Depth
        {
            set;
            get;
        }

// ReSharper disable InconsistentNaming
        public Boolean isDirectory { get { return IsDirectory(); } }
// ReSharper restore InconsistentNaming

        public virtual Boolean IsDirectory(){ return false;}

        private const String EmptyBytes = "";

        public int CompareTo(Object other)
        {
            if(other==null)
                throw new ArgumentNullException("can not compare to Null");
            if (other is String)
            {
                return String.CompareOrdinal(Name, other as string);
            }
            throw new ArgumentNullException("Argument is not String!");
        }

        public int CompareTo(NodeBase other)
        {
            if(null==other) throw new ArgumentNullException("the node is null");
            if(null==other.Name) throw new ArgumentNullException("the node's name is null");
            var left = Name ?? EmptyBytes;
            var right = other.Name ?? EmptyBytes;
            return String.CompareOrdinal(left, right);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((NodeBase) obj);
        }

        protected bool Equals(NodeBase other)
        {
            return Equals(Name, other.Name);
        }

        public override int GetHashCode()
        {
            return (Name != null ? Name.GetHashCode() : 0);
        }

        public virtual void WriteToBinary(BinaryWriter binaryWriter)
        {
            if (!binaryWriter.BaseStream.CanWrite) return;
            binaryWriter.Write(Name);
            binaryWriter.Write(CreateTime);
            binaryWriter.Write(LastUpdateTime);
            binaryWriter.Write(CreaterName);
            //binaryWriter.Write(FullPath);
            //binaryWriter.Write(Depth);
        }

        public virtual NodeBase ReadFromBinary(BinaryReader binaryReader)
        {
            if (!binaryReader.BaseStream.CanRead) return null;
            Name = binaryReader.ReadString();
            CreateTime = binaryReader.ReadInt64();
            LastUpdateTime = binaryReader.ReadInt64();
            CreaterName = binaryReader.ReadString();
            //FullPath = binaryReader.ReadString();
            //Depth = binaryReader.ReadInt32();
            return this;
        }
    }
}